package com.xbongbong.paas.script.controller;

import com.alibaba.fastjson.JSON;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasAppEntity;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasMenuEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.MenuTypeEnum;
import com.xbongbong.paas.help.menu.InitFundManagementMenuHelp;
import com.xbongbong.paas.help.menu.InitMenuHelp;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasMenuModel;
import com.xbongbong.paas.pojo.dto.FormEntityAddDTO;
import com.xbongbong.paas.pojo.dto.InitFundMenuDTO;
import com.xbongbong.paas.service.PaasFormService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.enums.AccessLinkEnum;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.menu.enums.FundManagementMenuEnum;
import com.xbongbong.pro.form.pojo.dto.FormAddBatchDTO;
import com.xbongbong.pro.form.pojo.vo.FormAddBatchVO;
import com.xbongbong.pro.menu.pojo.dto.MenuInitDTO;
import com.xbongbong.pro.script.pojo.vo.ScriptVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ext.PaymentSheetEntityExt;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.help.SaasPaymentSheetHelper;
import com.xbongbong.saas.model.PaymentSheetModel;
import com.xbongbong.saas.service.PaymentBalanceService;
import com.xbongbong.sys.domain.entity.CompanyEntity;
import com.xbongbong.sys.model.CompanyModel;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author zcp
 * @version v1.0
 * @date 19/11/4 004 10:34
 * @update 19/11/4 004 10:34
 * @since v1.0
 */
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/script/fund/menu")
public class FundMenuScriptController {
    private static final Logger LOG = LoggerFactory.getLogger(FundMenuScriptController.class);
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private PaasMenuModel paasMenuModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private CompanyModel companyModel;
    @Resource
    private PaymentSheetModel paymentSheetModel;
    @Resource
    private InitFundManagementMenuHelp initFundManagementMenuHelp;
    @Resource
    private PaasFormService paasFormService;
    @Resource
    private PaymentBalanceService paymentBalanceService;
    @Resource
    private InitMenuHelp initMenuHelp;
    @Resource
    private SaasPaymentSheetHelper saasPaymentSheetHelper;

    private static final Integer PRE_PAYMENT_BALANCE = 1;
    private static final Integer PRE_PAY_BALANCE = 2;

    /**
     * 初始化其他收支单的menu，及其他收入单、其他支出单单、资金调拨单的menu、form、explain，其中explain需要默认置空（结合corpid=0的数据去使用）
     * @param initFundMenuDTO
     * @param br
     * @return java.lang.String
     * @throws Exception
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    @RequestMapping(value = "/otherFund/init", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String otherFundInit(@RequestBody @Valid InitFundMenuDTO initFundMenuDTO, BindingResult br) throws Exception {
        XbbResponse<ScriptVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
            return JSON.toJSONString(response);
        } else {
            if (!proBaseConfig.getXbbCode().equals(initFundMenuDTO.getXbbCode())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
            }
            Integer full = initFundMenuDTO.getFlag();
            List<String> corpidList = initFundMenuDTO.getCorpidList();
            boolean fullFlag = true;
            if (Objects.equals(full, BasicConstant.ZERO)) {
                //非全量必须传入要处理的公司id集合
                if (CollectionsUtil.isEmpty(corpidList)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, "corpidList不能为空，请传入要部分提前处理的公司id集合");
                }
                fullFlag = false;
            } else {
                if (Objects.isNull(corpidList)) {
                    corpidList = new ArrayList<>();
                }
            }
            int pageSize = 1000;
            long timeStart = DateTimeUtil.getInt();
            Map<String, Object> appParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            //每个公司只有一个资金管理
            appParam.put("alias", XbbRefTypeEnum.FUND_MANAGEMENT.getAlias());
            appParam.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            List<FundManagementMenuEnum> parentGroupEnum = Collections.singletonList(FundManagementMenuEnum.OTHER_FUND_MANAGEMENT);
            List<FundManagementMenuEnum> childEnum = Arrays.asList(FundManagementMenuEnum.OTHER_INCOME, FundManagementMenuEnum.OTHER_EXPENSE, FundManagementMenuEnum.FUND_TRANSFER);
            //要插入的菜单枚举
            List<FundManagementMenuEnum> insertEnumList = new ArrayList<>();
            insertEnumList.addAll(parentGroupEnum);
            insertEnumList.addAll(childEnum);
            List<String> aliasIn = insertEnumList.stream().map(FundManagementMenuEnum::getAlias).collect(Collectors.toList());
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("del", 0);
            param.put("columns", "corpid");
            param.put("pageNum", pageSize);
            if (fullFlag) {
                int total = companyModel.getEntitysCount(param);
                for (int i = 0; i < total; i += pageSize) {
                    param.put("start", i);
                    List<CompanyEntity> companyEntityList = companyModel.findEntitys(param);
                    if (CollectionsUtil.isEmpty(companyEntityList)) {
                        continue;
                    }
                    List<String> corpids = companyEntityList.stream().map(CompanyEntity::getCorpid).collect(Collectors.toList());
                    //全量执行时，剔除已经处理过的公司id集合
                    corpids.removeAll(corpidList);
                    if (corpids.size() == 0) {
                        continue;
                    }
                    insertFundMenuFormAndExplain(initFundMenuDTO, corpids, appParam, aliasIn, parentGroupEnum, childEnum);
                    LOG.warn("第{}个，总计{}", (i + 1), total);
                }
            }else {
                insertFundMenuFormAndExplain(initFundMenuDTO, initFundMenuDTO.getCorpidList(), appParam, aliasIn, parentGroupEnum, childEnum);
            }
            LOG.warn("-----------/script/fund/menu/otherFundInit over time consume:{}", (DateTimeUtil.getInt() - timeStart));
        }
        return JSON.toJSONString("{\"msg\":\"success\"}");
    }

    /**
     * 插入资金管理菜单：回款管理、进项发票（付款管理可开发到时再插入）
     * @param initFundMenuDTO
     * @param br
     * @return java.lang.String
     * @author zcp
     * @date 19/11/4 004 16:20
     * @update 19/11/4 004 16:20
     * @since v1.0
     * @version v1.0
     */
    @RequestMapping(value = "/init", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String init(@RequestBody @Valid InitFundMenuDTO initFundMenuDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(initFundMenuDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> corpidList = initFundMenuDTO.getCorpidList();
        if (corpidList == null || corpidList.isEmpty()) {
            corpidList = companyModel.getCorpidList();
        }
        Integer totalCount = corpidList.size();
        LOG.warn("开始处理菜单相关，数据库中共有" + totalCount + "家公司");
        int pageSize = 100;
        int totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize) + 1;
        int lastPageSize = (totalCount % pageSize == 0) ? pageSize : (totalCount % pageSize);

        long timeStart = DateTimeUtil.getInt();
        String userId = initFundMenuDTO.getUserId();
        List<FundManagementMenuEnum> jxcFundEnumList = FundManagementMenuEnum.getJxcFund();
        // 已改为只有付款管理
        List<FundManagementMenuEnum> parentEnumList = FundManagementMenuEnum.getParentInsertEnum();
        List<String> jxcAliasList = new ArrayList<>();
        for (FundManagementMenuEnum cache : jxcFundEnumList) {
            jxcAliasList.add(cache.getAlias());
        }
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //每个公司只有一个资金管理
        param.put("alias", XbbRefTypeEnum.FUND_MANAGEMENT.getAlias());
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        for (int page = 0; page < totalPage; page++) {
            List<String> subCorpidList = subCorpidList(corpidList, pageSize, totalPage, lastPageSize, page);
            //只查出进销存部分的菜单，如果进销存未开启，则菜单（付款管理）都查不出，则这种公司都不用初始化（不能通过资金管理app去确定是否开启进销存，因为资金管理包含crm部分菜单，因此肯定有）
            List<PaasMenuEntity> fundMenuList = getPaasMenuList4Jxc(subCorpidList, jxcAliasList);
            if (fundMenuList.size() == 0) {
                //没有资金管理菜单，下面逻辑还用资金一期上线时的脚本逻辑执行（用资金app），不再改动
                LOG.warn("-----------没有资金管理菜单");
                continue;
            }
            List<PaasAppEntity> jxcFundAppList = getPaasAppList(subCorpidList, param);
            //corpid_alias-菜单
            Map<String, PaasMenuEntity> corpMenuMap = new HashMap<>(fundMenuList.size());
            //appId-应用下的菜单
            Map<Long, List<PaasMenuEntity>> appIdMenuMap = new HashMap<>(fundMenuList.size());
            formatMenuMap(fundMenuList, corpMenuMap, appIdMenuMap);
            //-------------------（1）先插入父级菜单：付款管理
            List<PaasMenuEntity> parentInserMenuList = insertParentMenuList(jxcFundAppList, parentEnumList, corpMenuMap, appIdMenuMap, userId, DelEnum.NORMAL.getDel());
            //父级菜单也塞入map
            formatMenuMap(parentInserMenuList, corpMenuMap, appIdMenuMap);
            //-------------------（2）处理子级菜单：付款计划、付款单、进项发票
            List<PaasMenuEntity> childInsertList = handleChildMenu(jxcFundAppList, jxcFundEnumList, corpMenuMap, appIdMenuMap, userId);
            //子级新插入的菜单也塞入map
            formatMenuMap(childInsertList, corpMenuMap, appIdMenuMap);
            //-------------------（3）处理tb_paas_form原付款单：把其menuId置为上面新生成的付款单menuId，并处理menuId、summary、customTitle等
            String keyPart = "_" + FundManagementMenuEnum.PAY_SHEET.getAlias();
            //在上一步查询getPaasAppList时，param内已经塞入过corpidIn、saasMark
            param.put("businessType", XbbRefTypeEnum.PAY_SHEET.getCode());
            List<PaasFormEntityExt> sheetFormList = paasFormModel.getByBusinessTypes(param);
            handleForm4Sheet(sheetFormList, keyPart, corpMenuMap);
            /* 改为sql处理
            //-------------------（4）处理tb_paas_form_explain原付款单：把其menuId置为上面新生成的付款单menuId
            List<PaasFormExplainEntityExt> sheetFormExplainList = paasFormExplainModel.findEntityExt(param);
            handleFormExplain4Sheet(sheetFormExplainList, keyPart, corpMenuMap);
            */
            Integer start = page + 1;
            LOG.warn("处理进度" + start + "/" + totalPage);
            param.remove("columns");
            param.remove("businessType");
        }
        LOG.warn("-----------/script/fund/menu/init over 菜单相关处理完毕 time consume:" + (DateTimeUtil.getInt() - timeStart));
        return "处理完毕";
    }

    /**
     * 初始化对账单（对账单、生成对账单、对账单列表）的菜单、表单、表单解释(tb_paas_menu默认是已删除的状态)
     * @param initFundMenuDTO
     * @param br
     * @return java.lang.String
     * @throws Exception
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    @RequestMapping(value = "/customerStatement/init", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String customerStatementInit(@RequestBody @Valid InitFundMenuDTO initFundMenuDTO, BindingResult br) throws Exception {
        XbbResponse<ScriptVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
            return JSON.toJSONString(response);
        } else {
            if (!proBaseConfig.getXbbCode().equals(initFundMenuDTO.getXbbCode())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
            }
            List<String> corpidList = initFundMenuDTO.getCorpidList();
            int pageSize = 1000;
            long timeStart = DateTimeUtil.getInt();
            Map<String, Object> menuParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            //每个公司只有一个资金管理
            menuParam.put("alias", XbbRefTypeEnum.FUND_MANAGEMENT.getAlias());
            menuParam.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            //要插入的菜单枚举
            List<FundManagementMenuEnum> insertEnumList = Arrays.asList(FundManagementMenuEnum.STATEMENT, FundManagementMenuEnum.CUSTOMER_STATEMENT, FundManagementMenuEnum.CUSTOMER_STATEMENT_STATISTIC);
            List<String> aliasIn = insertEnumList.stream().map(FundManagementMenuEnum::getAlias).collect(Collectors.toList());
            if (corpidList == null || corpidList.isEmpty()) {
                Map<String, Object> param = new HashMap<>(16);
                param.put("del", 0);
                param.put("columns", "corpid");
                param.put("shouldUpdateTime",initFundMenuDTO.getShouldUpdateTime());
                param.put("shouldUpdateEndTime",initFundMenuDTO.getShouldUpdateEndTime());
                int total = companyModel.getEntitysCount(param);
                for (int i = 0; i < total; i += pageSize) {
                    param.put("start", i);
                    param.put("pageNum", pageSize);
                    List<CompanyEntity> companyEntityList = companyModel.findEntitys(param);
                    if (CollectionsUtil.isEmpty(companyEntityList)) {
                        continue;
                    }
                    List<String> corpids = companyEntityList.stream().map(CompanyEntity::getCorpid).collect(Collectors.toList());
                    insertStatementMenuFormAndExplain(initFundMenuDTO, corpids, menuParam, aliasIn);

                    LOG.warn("第" + (i + 1) + "个，总计" + total);
                }
            }else {
                insertStatementMenuFormAndExplain(initFundMenuDTO, initFundMenuDTO.getCorpidList(), menuParam, aliasIn);
            }
            LOG.warn("-----------/script/fund/menu/initForm over time consume:" + (DateTimeUtil.getInt() - timeStart));
        }
        return JSON.toJSONString("{\"msg\":\"success\"}");
    }

    /**
     * 得到所有的菜单
     *
     * @param corpidList
     * @param aliasIn
     * @return
     */
    private List<PaasMenuEntity> getAllPaasMenuList(List<String> corpidList, List<String> aliasIn) {
        Map<String, Object> menuParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        menuParam.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        menuParam.put("corpidIn", corpidList);
        menuParam.put("aliasIn", aliasIn);
        menuParam.put("del", 0);
        return paasMenuModel.findEntitys(menuParam);
    }

    /**
     * 获取需要插入的表单数据
     *
     * @param menuList
     * @return
     */
    private List<FormEntityAddDTO> getFormList(List<PaasMenuEntity> menuList) {
        List<FormEntityAddDTO> formList = new ArrayList<>();
        for (PaasMenuEntity item : menuList) {
            try {
                FormEntityAddDTO formEntityAddDTO = new FormEntityAddDTO();
                BeanUtil.copyProperties(item, formEntityAddDTO);
                FundManagementMenuEnum fundManagementMenuEnum = FundManagementMenuEnum.getByAlias(item.getAlias());
                if (Objects.isNull(fundManagementMenuEnum)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.BUSINESS_TYPE_NOT_EXIST);
                }
                formEntityAddDTO.setBusinessType(fundManagementMenuEnum.getCode());
                formEntityAddDTO.setSaasMark(SaasMarkEnum.SAAS.getCode());
                //formEntityAddDTO.setLabels(initMenuHelp.getAppDefaultLabel(fundManagementMenuEnum.getCode()));
                //formEntityAddDTO.setCustomTitle(initMenuHelp.getAppDefaultTitle(fundManagementMenuEnum.getCode()));
                //.setSummaryEntity(initMenuHelp.getAppDefaultSummary(fundManagementMenuEnum.getCode()));
                formEntityAddDTO.setBusinessRules("0");
                formEntityAddDTO.setMenuId(item.getId());
                formEntityAddDTO.setDistributorMark(DistributorMarkEnum.OTHER.getCode());
                formList.add(formEntityAddDTO);
            } catch (Exception e) {
                LOG.error("公司（corpid=" + item.getCorpid() + "）的" + item.getName() + "form初始化错误，FundMenuScriptController.getFormList 出错", e);
            }
        }
        return formList;
    }



    /**
     * 判断公司资金管理这个应用是否起着
     *
     * @param corpids
     * @param alias
     * @return
     */
    private List<PaasAppEntity> appEnableList(List<String> corpids, String alias) {
        Map<String,Object> appParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        appParam.put("del", 0);
        appParam.put("corpidIn", corpids);
        appParam.put("alias", alias);
        appParam.put("enable",BasicConstant.ONE);
        return paasAppModel.findEntitys(appParam);
    }


    /**
     * 预收款和预付款表单和解释的处理
     * @param initFundMenuDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/initForm", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String initForm(@RequestBody @Valid InitFundMenuDTO initFundMenuDTO, BindingResult br) throws Exception {
        XbbResponse<ScriptVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
            return JSON.toJSONString(response);
        } else {
            if (!proBaseConfig.getXbbCode().equals(initFundMenuDTO.getXbbCode())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
            }
            List<String> corpidList = initFundMenuDTO.getCorpidList();
            int pageSize = 1000;
            long timeStart = DateTimeUtil.getInt();
            if (corpidList == null || corpidList.isEmpty()) {
                Map<String, Object> param = new HashMap<>(16);
                param.put("del", 0);
                int total = companyModel.getEntitysCount(param);
                for (int i = 0; i < total; i += pageSize) {
                    param.clear();
                    param.put("del", 0);
                    param.put("start", i);
                    param.put("pageNum", pageSize);
                    param.put("columns", "corpid");
                    List<CompanyEntity> companyEntityList = companyModel.findEntitys(param);
                    if (Objects.isNull(companyEntityList) || companyEntityList.isEmpty()) {
                        continue;
                    }
                    List<String> corpids = new ArrayList<>(companyEntityList.size());
                    companyEntityList.forEach(item -> {
                        corpids.add(item.getCorpid());
                    });
                    insertFormId(initFundMenuDTO, corpids, PRE_PAY_BALANCE);
                    LOG.warn("第" + i + "个1000/" + total);
                }
            }else {
                insertFormId(initFundMenuDTO, initFundMenuDTO.getCorpidList(), PRE_PAY_BALANCE);
            }
            LOG.warn("-----------time consume:" + (DateTimeUtil.getInt() - timeStart));
            LOG.warn("-----------/script/fund/menu/initForm over");
        }
        return JSON.toJSONString("{\"msg\":\"success\"}");
    }

    /**
     * 后面方法的限制，只能单个公司处理
     * @param initFundMenuDTO
     * @param corpids
     * @throws XbbException
     */
    private void insertFormId( InitFundMenuDTO initFundMenuDTO, List<String> corpids, Integer businessType) throws XbbException {
        if(CollectionsUtil.isEmpty(corpids)){
            return;
        }
        for (String corpid : corpids) {
            PaasFormEntityExt paasFormEntityExt = new PaasFormEntityExt();
            if (Objects.equals(businessType, PRE_PAYMENT_BALANCE)) {
                paasFormEntityExt = paasFormModel.getByBusinessType(XbbRefTypeEnum.PREPAYMENT_BALANCE.getCode(), corpid);
            } else if (Objects.equals(businessType, PRE_PAY_BALANCE)) {
                paasFormEntityExt = paasFormModel.getByBusinessType(XbbRefTypeEnum.PREPAY_BALANCE.getCode(), corpid);
            }
            //不存在的才需要处理，存在的跳过
            if(paasFormEntityExt !=null){
                continue;
            }
            Map<String, Object> menuParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (Objects.equals(businessType, PRE_PAYMENT_BALANCE)) {
                menuParam.put("alias", XbbRefTypeEnum.PREPAYMENT_BALANCE.getAlias());
            } else if (Objects.equals(businessType, PRE_PAY_BALANCE)) {
                menuParam.put("alias", XbbRefTypeEnum.PREPAY_BALANCE.getAlias());
            }
            menuParam.put("corpid", corpid);
            List<PaasMenuEntity> menuEntities = paasMenuModel.findEntitys(menuParam);
            //菜单默认是关闭的，会影响后面
            for (PaasMenuEntity menuEntity : menuEntities) {
                menuEntity.setEnable(1);
            }
            List<FormEntityAddDTO> formList = new ArrayList<>();
            // 插入菜单对应的表单
            FormAddBatchDTO formAddBatchDTO = new FormAddBatchDTO();
            BeanUtil.copyProperties(initFundMenuDTO, formAddBatchDTO);
            initFundManagementMenuHelp.getPrePaymentFormList(formList, menuEntities);
            formAddBatchDTO.setFormList(formList);
            formAddBatchDTO.setCorpid(corpid);
            FormAddBatchVO formAddBatchVO = paasFormService.addBatch(formAddBatchDTO);
            if (Objects.isNull(formAddBatchVO)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            MenuInitDTO menuInitDTO = new MenuInitDTO();
            BeanUtil.copyProperties(initFundMenuDTO, menuInitDTO);
            menuInitDTO.setCorpid(corpid);
            // 插入表单对应的字段解释
            initFundManagementMenuHelp.formExplainAddBatch(menuInitDTO, formAddBatchVO);
        }
    }

    /**
     * 后面方法的限制，只能单个公司处理
     * 处理客户对账单form、explain
     * @param initFundMenuDTO
     * @param corpids 公司id集合
     * @param menuParam 查询app的参数map
     * @param aliasIn 对账单alias list
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void insertStatementMenuFormAndExplain(InitFundMenuDTO initFundMenuDTO, List<String> corpids, Map<String, Object> menuParam, List<String> aliasIn) throws XbbException {
        List<PaasAppEntity> fundAppList = getPaasAppList(corpids, menuParam);
        List<PaasMenuEntity> fundMenuList = getPaasMenuList(aliasIn, fundAppList);
        //corpid_alias-菜单
        Map<String, PaasMenuEntity> corpMenuMap = new HashMap<>(16);
        //appId-应用下的菜单
        Map<Long, List<PaasMenuEntity>> appIdMenuMap = new HashMap<>(16);
        formatMenuMap(fundMenuList, corpMenuMap, appIdMenuMap);
        List<FundManagementMenuEnum> parentEnum = Collections.singletonList(FundManagementMenuEnum.STATEMENT);
        List<FundManagementMenuEnum> childEnum = Arrays.asList(FundManagementMenuEnum.CUSTOMER_STATEMENT, FundManagementMenuEnum.CUSTOMER_STATEMENT_STATISTIC);
        //-------------------插入客户对账单菜单，先置为删除状态
        List<PaasMenuEntity> insertStatementParentMenuList = insertParentMenuList(fundAppList, parentEnum, corpMenuMap, appIdMenuMap, initFundMenuDTO.getUserId(), DelEnum.DELETE.getDel());
        List<PaasMenuEntity> insertStatementMenuList = insertChildMenuList(fundAppList, childEnum, corpMenuMap, appIdMenuMap, initFundMenuDTO.getUserId(), insertStatementParentMenuList, DelEnum.DELETE.getDel());
        //得到要插入的formList
        List<PaasFormEntity> insertFormList = initFundManagementMenuHelp.getCustomerStatementFormList(corpids, insertStatementMenuList);
        if (CollectionUtils.isNotEmpty(insertFormList)) {
            paasFormModel.insertBatch(insertFormList);

            FormAddBatchVO formAddBatchVO;
            //formExplainAddBatch方法内部用到corpid
            for (PaasFormEntity paasFormEntity : insertFormList) {
                formAddBatchVO = new FormAddBatchVO();
                formAddBatchVO.setFormList(Collections.singletonList(paasFormEntity));
                MenuInitDTO menuInitDTO = new MenuInitDTO();
                BeanUtil.copyProperties(initFundMenuDTO, menuInitDTO);
                menuInitDTO.setCorpid(paasFormEntity.getCorpid());
                // 插入表单对应的字段解释
                try {
                    initFundManagementMenuHelp.formExplainAddBatch(menuInitDTO, formAddBatchVO);
                } catch (Exception e) {
                    //失败不暂定，继续往下执行
                    LOG.error("公司（corpid=" + paasFormEntity.getCorpid() + "）的explain初始化失败，未生成其对应explain，insertStatementMenuFormAndExplain");
                }
            }
        }
    }

    /**
     * 初始化生成对账单，对账单列表的菜单
     * @param fundAppList
     * @param enumList
     * @param corpMenuMap
     * @param appIdMenuMap
     * @param userId
     * @param parentMenuList
     * @param del
     * @return
     * @throws XbbException
     */
    private List<PaasMenuEntity> insertChildMenuList(List<PaasAppEntity> fundAppList, List<FundManagementMenuEnum> enumList, Map<String, PaasMenuEntity> corpMenuMap, Map<Long, List<PaasMenuEntity>> appIdMenuMap, String userId, List<PaasMenuEntity> parentMenuList, Integer del) throws XbbException {
        List<PaasMenuEntity> insertList = new ArrayList<>();
        Map<String, PaasMenuEntity> paasMenuEntityMap = parentMenuList.stream().collect(Collectors.toMap(PaasMenuEntity::getCorpid,v->v, (v1,v2)->v1));
        for (PaasAppEntity entity : fundAppList) {
            Long appId = entity.getId();
            String corpid = entity.getCorpid();
            String key = corpid + "_";
            List<PaasMenuEntity> menuSet = appIdMenuMap.getOrDefault(appId, new ArrayList<>());
            for (FundManagementMenuEnum cache : enumList) {
                String alias = cache.getAlias();
                PaasMenuEntity paasMenuEntity = corpMenuMap.get(key + alias);
                if (paasMenuEntity != null) {
                    //不更新，只插入
                    break;
                }
                AccessLinkEnum accessLinkEnum = cache.getAccessLinkEnum();
                int sort = 0;
                if (menuSet.size() > 0) {
                    sort = menuSet.get(0).getSort() + 1;
                }
                paasMenuEntity = new PaasMenuEntity(corpid, appId, cache.getName(), alias, sort, accessLinkEnum.getUrl(), accessLinkEnum.getMobileUrl(), BasicConstant.ONE, accessLinkEnum.getColor(), accessLinkEnum.getIcon(), userId);
                switch (cache) {
                    case CUSTOMER_STATEMENT:
                    case CUSTOMER_STATEMENT_STATISTIC:
                        paasMenuEntity.setParentId(paasMenuEntityMap.get(corpid).getId());
                        paasMenuEntity.setType(MenuTypeEnum.FORM.getType());
                        paasMenuEntity.setDistributorMark(DistributorMarkEnum.OTHER.getCode());
                        break;
                    default:
                        continue;
                }
                paasMenuEntity.setDel(del);
                insertList.add(paasMenuEntity);
            }
        }
        try {
            if (insertList.size() > 0) {
                insertList = paasMenuModel.insertBatch(insertList);
            }
        } catch (Exception e) {
            LOG.error("FundMenuScriptController.insertParentMenuList menu数据库批量插入菜单出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        LOG.warn(insertList.size() + "条子级菜单插入成功");
        return insertList;
    }

    /**
     * 初始化子级的菜单
     * @param fundAppList
     * @param enumList
     * @param corpMenuMap
     * @param appIdMenuMap
     * @param userId
     * @param parentMenuList
     * @param del
     * @return
     * @throws XbbException
     */
    private List<PaasMenuEntity> insertChildMenuListSen(List<PaasAppEntity> fundAppList, List<FundManagementMenuEnum> enumList, Map<String, PaasMenuEntity> corpMenuMap, Map<Long, List<PaasMenuEntity>> appIdMenuMap, String userId, List<PaasMenuEntity> parentMenuList, Integer del) throws XbbException {
        List<PaasMenuEntity> insertList = new ArrayList<>();
        Map<String, PaasMenuEntity> paasMenuEntityMap = parentMenuList.stream().collect(Collectors.toMap(PaasMenuEntity::getCorpid,v->v, (v1,v2)->v1));
        for (PaasAppEntity entity : fundAppList) {
            Long appId = entity.getId();
            String corpid = entity.getCorpid();
            String key = corpid + "_";
//            List<PaasMenuEntity> menuSet = appIdMenuMap.getOrDefault(appId, new ArrayList<>());
            for (FundManagementMenuEnum cache : enumList) {
                String alias = cache.getAlias();
                PaasMenuEntity paasMenuEntity = corpMenuMap.get(key + alias);
                if (paasMenuEntity != null) {
                    //不更新，只插入
                    break;
                }
                AccessLinkEnum accessLinkEnum = cache.getAccessLinkEnum();
                int sort = 999;
                paasMenuEntity = new PaasMenuEntity(corpid, appId, cache.getName(), alias, sort, accessLinkEnum.getUrl(), accessLinkEnum.getMobileUrl(), BasicConstant.ONE, accessLinkEnum.getColor(), accessLinkEnum.getIcon(), userId);
                switch (cache) {
                    case OTHER_INCOME:
                    case OTHER_EXPENSE:
                        paasMenuEntity.setParentId(paasMenuEntityMap.get(corpid).getId());
                        paasMenuEntity.setType(MenuTypeEnum.FORM.getType());
                        paasMenuEntity.setDistributorMark(DistributorMarkEnum.OTHER.getCode());
                        break;
                    case FUND_TRANSFER:
                        paasMenuEntity.setSort(1000);
                        //资金调拨单无父级，不用设置parentId（直接归属到资金管理app下）
                        paasMenuEntity.setType(MenuTypeEnum.FORM.getType());
                        paasMenuEntity.setDistributorMark(DistributorMarkEnum.OTHER.getCode());
                        break;
                    default:
                        continue;
                }
                paasMenuEntity.setDel(del);
                insertList.add(paasMenuEntity);
            }
        }
        try {
            if (insertList.size() > 0) {
                insertList = paasMenuModel.insertBatch(insertList);
            }
        } catch (Exception e) {
            LOG.error("FundMenuScriptController.insertParentMenuList menu数据库批量插入菜单出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        LOG.warn(insertList.size() + "条子级菜单插入成功");
        return insertList;
    }

    /**
     * 后面方法的限制，只能单个公司处理
     * 处理客户对账单form、explain
     * @param initFundMenuDTO
     * @param corpids 公司id集合
     * @param appParam 查询app的参数map
     * @param aliasIn 对账单alias list
     * @param parentGroupEnum 父级group类型的菜单
     * @param childEnum form类型的普通菜单
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void insertFundMenuFormAndExplain(InitFundMenuDTO initFundMenuDTO, List<String> corpids, Map<String, Object> appParam, List<String> aliasIn, List<FundManagementMenuEnum> parentGroupEnum, List<FundManagementMenuEnum> childEnum) throws XbbException {
        List<PaasAppEntity> fundAppList = getPaasAppList(corpids, appParam);
        List<PaasMenuEntity> fundMenuList = getPaasMenuList(aliasIn, fundAppList);
        //corpid_alias-菜单
        Map<String, PaasMenuEntity> corpMenuMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //appId-应用下的菜单
        Map<Long, List<PaasMenuEntity>> appIdMenuMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        formatMenuMap(fundMenuList, corpMenuMap, appIdMenuMap);
        //-------------------插入菜单
        //父级group类型的菜单
        //TODO 这边先临时特殊处理一下，就是资金paas化的那几个表单，用传鹏在资金paas化那边的脚本，后面回来再做决定
        List<PaasMenuEntity> insertParentGroupMenuList = new ArrayList<>();
        List<PaasMenuEntity> insertChildMenuList = new ArrayList<>();
        if (parentGroupEnum.contains(FundManagementMenuEnum.OTHER_FUND_MANAGEMENT)) {
            insertParentGroupMenuList = insertParentMenuListSen(fundAppList, parentGroupEnum, corpMenuMap, appIdMenuMap, initFundMenuDTO.getUserId(), DelEnum.NORMAL.getDel());
            //子级form类型的菜单
            insertChildMenuList = insertChildMenuListSen(fundAppList, childEnum, corpMenuMap, appIdMenuMap, initFundMenuDTO.getUserId(), insertParentGroupMenuList, DelEnum.NORMAL.getDel());
        }else {
            insertParentGroupMenuList = insertParentMenuList(fundAppList, parentGroupEnum, corpMenuMap, appIdMenuMap, initFundMenuDTO.getUserId(), DelEnum.NORMAL.getDel());
            //子级form类型的菜单
            insertChildMenuList = insertChildMenuList(fundAppList, childEnum, corpMenuMap, appIdMenuMap, initFundMenuDTO.getUserId(), insertParentGroupMenuList, DelEnum.NORMAL.getDel());
        }
       //-------------------插入form
        //得到要插入的formList
        List<PaasFormEntity> insertFormList = initFundManagementMenuHelp.getSingleFormList(corpids, insertChildMenuList, childEnum);
        if (CollectionUtils.isNotEmpty(insertFormList)) {
            paasFormModel.insertBatch(insertFormList);

            FormAddBatchVO formAddBatchVO;
            //formExplainAddBatch方法内部用到corpid
            for (PaasFormEntity paasFormEntity : insertFormList) {
                formAddBatchVO = new FormAddBatchVO();
                formAddBatchVO.setFormList(Collections.singletonList(paasFormEntity));
                MenuInitDTO menuInitDTO = new MenuInitDTO();
                BeanUtil.copyProperties(initFundMenuDTO, menuInitDTO);
                menuInitDTO.setCorpid(paasFormEntity.getCorpid());
                // 插入表单对应的字段解释
                try {
                    initFundManagementMenuHelp.formExplainAddBatch(menuInitDTO, formAddBatchVO);
                } catch (Exception e) {
                    //失败不暂定，继续往下执行
                    LOG.error("公司（corpid=" + paasFormEntity.getCorpid() + "）的explain初始化失败，未生成其对应explain，insertFundMenuFormAndExplain");
                }
            }
        }
    }

    /**
     * 得到当前页的公司id列表
     * @param corpidList 所有的公司id列表
     * @param pageSize 每页个数
     * @param totalPage 总页数
     * @param lastPageSize 最后一页的个数
     * @param page 页码
     * @return java.util.List<java.lang.String>
     * @author zcp
     * @date 19/11/5 005 20:45in
     * @update 19/11/5 005 20:45
     * @since v1.0
     * @version v1.0
     */
    private List<String> subCorpidList(List<String> corpidList, int pageSize, int totalPage, int lastPageSize, int page) {
        int fromIndex = page * pageSize;
        int toIndex = fromIndex + pageSize;
        if (page == totalPage - 1) {
            toIndex = fromIndex + lastPageSize;
        }
        return corpidList.subList(fromIndex, toIndex);
    }

    /**
     * 得到某个分页内公司的appList
     * @param subCorpidList 当页corpidList
     * @param param 参数
     * @return java.util.List<com.xbongbong.paas.domain.entity.PaasAppEntity>
     * @author zcp
     * @date 19/11/4 004 15:30
     * @update 19/11/4 004 15:30
     * @since v1.0
     * @version v1.0
     */
    private List<PaasAppEntity> getPaasAppList(List<String> subCorpidList, Map<String, Object> param) {
        param.put("corpidIn", subCorpidList);
        param.put("saasMark", SaasMarkEnum.SAAS.getCode());
        return paasAppModel.findEntitys(param);
    }

    /**
     * 获取应用的菜单list
     * @param aliasIn 枚举list
     * @param fundAppList 应用list
     * @return java.util.List<com.xbongbong.paas.domain.entity.PaasMenuEntity>
     * @author zcp
     * @date 19/11/4 004 16:28
     * @update 19/11/4 004 16:28
     * @since v1.0
     * @version v1.0
     */
    private List<PaasMenuEntity> getPaasMenuList(List<String> aliasIn, List<PaasAppEntity> fundAppList) {
        List<Long> appIds = new ArrayList<>();
        fundAppList.forEach(item -> appIds.add(item.getId()));

        Map<String, Object> menuParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        menuParam.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        menuParam.put("appIdList", appIds);
        menuParam.put("aliasIn", aliasIn);
        //菜单默认按照sort ASC, update_time ASC排序，而新插入的菜单，要排到后面，因此读取排到最后的一个一个菜单即可
        menuParam.put("orderByStr", " sort DESC, update_time DESC ");
        return paasMenuModel.findEntitys(menuParam);
    }
    /**
     * 只通过alias查询出菜单list（二期的时候，只查进销存部分的菜单，而如果进销存未开启对应菜单是不会初始化的）
     * @param corpidList
     * @param aliasIn
     * @return java.util.List<com.xbongbong.paas.domain.entity.PaasMenuEntity>
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private List<PaasMenuEntity> getPaasMenuList4Jxc(List<String> corpidList, List<String> aliasIn) {
        Map<String, Object> menuParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        menuParam.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        menuParam.put("corpidIn", corpidList);
        menuParam.put("aliasIn", aliasIn);
        menuParam.put("del", 0);
        return paasMenuModel.findEntitys(menuParam);
    }

    /**
     * 格式化菜单，处理成相应的对应关系map
     * @param fundMenuList 资金管理菜单
     * @param corpMenuMap corpid_alias-菜单
     * @param appIdMenuMap appId-应用下的菜单
     * @author zcp
     * @date 19/11/4 004 17:19
     * @update 19/11/4 004 17:19
     * @since v1.0
     * @version v1.0
     */
    private void formatMenuMap(List<PaasMenuEntity> fundMenuList, Map<String, PaasMenuEntity> corpMenuMap, Map<Long, List<PaasMenuEntity>> appIdMenuMap) {
        for (PaasMenuEntity entity : fundMenuList) {
            corpMenuMap.put(entity.getCorpid() + "_" + entity.getAlias(), entity);
            Long appId = entity.getAppId();
            List<PaasMenuEntity> menuList = appIdMenuMap.getOrDefault(appId, new ArrayList<>());
            menuList.add(entity);
            appIdMenuMap.put(appId, menuList);
        }
    }

    /**
     * 插入父级的菜单，如回款管理、进项发票（付款管理暂不处理）、其他收支单
     * 注：不更新，只插入
     * @param fundAppList 资金管理所有appList
     * @param insertParentEnumList 要插入的父级菜单枚举list
     * @param corpMenuMap corpid_alias-菜单
     * @param appIdMenuMap appId-应用下的菜单
     * @param userId 登录userId
     * @param del
     * @return java.util.List<com.xbongbong.paas.domain.entity.PaasMenuEntity>
     * @throws XbbException
     * @author zcp
     * @date 19/11/4 004 17:05
     * @update 19/11/4 004 17:05
     * @since v1.0
     * @version v1.0
     */
    private List<PaasMenuEntity> insertParentMenuList(List<PaasAppEntity> fundAppList, List<FundManagementMenuEnum> insertParentEnumList, Map<String, PaasMenuEntity> corpMenuMap, Map<Long, List<PaasMenuEntity>> appIdMenuMap, String userId, Integer del) throws XbbException {
        List<PaasMenuEntity> insertList = new ArrayList<>();
        for (PaasAppEntity entity : fundAppList) {
            Long appId = entity.getId();
            String corpid = entity.getCorpid();
            String key = corpid + "_";
            List<PaasMenuEntity> menuSet = appIdMenuMap.getOrDefault(appId, new ArrayList<>());
            for (FundManagementMenuEnum cache : insertParentEnumList) {
                String alias = cache.getAlias();
                PaasMenuEntity paasMenuEntity = corpMenuMap.get(key + alias);
                if (paasMenuEntity != null) {
                    //不更新，只插入
                    break;
                }
                AccessLinkEnum accessLinkEnum = cache.getAccessLinkEnum();
                int sort = 0;
                if (menuSet.size() > 0) {
                    sort = menuSet.get(0).getSort() + 1;
                }
                paasMenuEntity = new PaasMenuEntity(corpid, appId, cache.getName(), alias, sort, accessLinkEnum.getUrl(), accessLinkEnum.getMobileUrl(), BasicConstant.ONE, accessLinkEnum.getColor(), accessLinkEnum.getIcon(), userId);
                switch (cache) {
                    case PAY_MANAGEMENT:
                    case STATEMENT:
                        paasMenuEntity.setType(MenuTypeEnum.GROUP.getType());
                        paasMenuEntity.setDistributorMark(DistributorMarkEnum.OTHER.getCode());
                        break;
                    default:
                        continue;
                }
                paasMenuEntity.setDel(del);
                insertList.add(paasMenuEntity);
            }
        }
        try {
            if (insertList.size() > 0) {
                insertList = paasMenuModel.insertBatch(insertList);
            }
        } catch (Exception e) {
            LOG.error("FundMenuScriptController.insertParentMenuList menu数据库批量插入菜单出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        LOG.warn(insertList.size() + "条父级菜单插入成功");
        return insertList;
    }


    /**
     * 插入父级的菜单，如回款管理、进项发票（付款管理暂不处理）、其他收支单
     * 注：不更新，只插入
     * @param fundAppList 资金管理所有appList
     * @param insertParentEnumList 要插入的父级菜单枚举list
     * @param corpMenuMap corpid_alias-菜单
     * @param appIdMenuMap appId-应用下的菜单
     * @param userId 登录userId
     * @param del
     * @return java.util.List<com.xbongbong.paas.domain.entity.PaasMenuEntity>
     * @throws XbbException
     * @author zcp
     * @date 19/11/4 004 17:05
     * @update 19/11/4 004 17:05
     * @since v1.0
     * @version v1.0
     */
    private List<PaasMenuEntity> insertParentMenuListSen(List<PaasAppEntity> fundAppList, List<FundManagementMenuEnum> insertParentEnumList, Map<String, PaasMenuEntity> corpMenuMap, Map<Long, List<PaasMenuEntity>> appIdMenuMap, String userId, Integer del) throws XbbException {
        List<PaasMenuEntity> insertList = new ArrayList<>();
        for (PaasAppEntity entity : fundAppList) {
            Long appId = entity.getId();
            String corpid = entity.getCorpid();
            String key = corpid + "_";
//            List<PaasMenuEntity> menuSet = appIdMenuMap.getOrDefault(appId, new ArrayList<>());
            for (FundManagementMenuEnum cache : insertParentEnumList) {
                String alias = cache.getAlias();
                PaasMenuEntity paasMenuEntity = corpMenuMap.get(key + alias);
                if (paasMenuEntity != null) {
                    //不更新，只插入
                    break;
                }
                AccessLinkEnum accessLinkEnum = cache.getAccessLinkEnum();
                int sort = 999;
                paasMenuEntity = new PaasMenuEntity(corpid, appId, cache.getName(), alias, sort, accessLinkEnum.getUrl(), accessLinkEnum.getMobileUrl(), BasicConstant.ONE, accessLinkEnum.getColor(), accessLinkEnum.getIcon(), userId);
                switch (cache) {
                    case OTHER_FUND_MANAGEMENT:
                        paasMenuEntity.setType(MenuTypeEnum.GROUP.getType());
                        paasMenuEntity.setDistributorMark(DistributorMarkEnum.OTHER.getCode());
                        break;
                    default:
                        continue;
                }
                paasMenuEntity.setDel(del);
                insertList.add(paasMenuEntity);
            }
        }
        try {
            if (insertList.size() > 0) {
                insertList = paasMenuModel.insertBatch(insertList);
            }
        } catch (Exception e) {
            LOG.error("FundMenuScriptController.insertParentMenuList menu数据库批量插入菜单出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        LOG.warn(insertList.size() + "条父级菜单插入成功");
        return insertList;
    }

    /**
     * 处理子菜单
     * @param fundAppList 资金管理所有appList
     * @param someFundEnumList 需要处理菜单的资金管理枚举list（一期、二期不一样）
     * @param corpMenuMap corpid_alias-菜单
     * @param appIdMenuMap appId-应用下的菜单
     * @param userId 登录员工userId
     * @return java.util.List<com.xbongbong.paas.domain.entity.PaasMenuEntity>
     * @throws XbbException
     * @author zcp
     * @date 19/11/4 004 19:59
     * @update 19/11/4 004 19:59
     * @since v1.0
     * @version v1.0
     */
    private List<PaasMenuEntity> handleChildMenu(List<PaasAppEntity> fundAppList, List<FundManagementMenuEnum> someFundEnumList, Map<String, PaasMenuEntity> corpMenuMap, Map<Long, List<PaasMenuEntity>> appIdMenuMap, String userId) throws XbbException {
        List<PaasMenuEntity> insertList = new ArrayList<>();
        List<PaasMenuEntity> updateList = new ArrayList<>();
        for (PaasAppEntity entity : fundAppList) {
            Long appId = entity.getId();
            String corpid = entity.getCorpid();
            String key = corpid + "_";
            List<PaasMenuEntity> menuSet = appIdMenuMap.getOrDefault(appId, new ArrayList<>());
            for (FundManagementMenuEnum cache : someFundEnumList) {
                String alias = cache.getAlias();
                String name = cache.getName();
                PaasMenuEntity paasMenuEntity = corpMenuMap.get(key + alias);
                boolean flag = false;
                AccessLinkEnum accessLinkEnum = cache.getAccessLinkEnum();
                if (paasMenuEntity == null) {
                    flag = true;
                    //预收、付款则默认关闭
                    Integer enable = (Objects.equals(alias, FundManagementMenuEnum.PREPAY_BLANCE.getAlias()))? BasicConstant.ZERO: BasicConstant.ONE;
                    int sort = 0;
                    if (menuSet.size() > 0) {
                        sort = menuSet.get(0).getSort() + 1;
                    }
                    paasMenuEntity = new PaasMenuEntity(corpid, appId, name, alias, sort, accessLinkEnum.getUrl(), accessLinkEnum.getMobileUrl(), enable, accessLinkEnum.getColor(), accessLinkEnum.getIcon(), userId);
                }
                //图标和颜色大部分都做了修改，因此强制set
                paasMenuEntity.setIcon(accessLinkEnum.getIcon());
                paasMenuEntity.setColor(accessLinkEnum.getColor());
                paasMenuEntity.setUrl(accessLinkEnum.getUrl());
                paasMenuEntity.setMobileUrl(accessLinkEnum.getMobileUrl());
                switch (cache) {
                    case PAY_MANAGEMENT:
                        //付款管理insertParentMenuList内已经插入
                        //此处需更新其icon、color
                        paasMenuEntity.setType(MenuTypeEnum.GROUP.getType());
                        break;
                    case PAY_PLAN:
                        //原pro付款管理名称改为付款计划
                        if (Objects.equals(paasMenuEntity.getName(), "付款管理")) {
                            paasMenuEntity.setName(name);
                        }
                        //付款计划：强制不是流程表单
                        paasMenuEntity.setType(MenuTypeEnum.FORM.getType());
                        setParentId(corpid, cache, corpMenuMap, paasMenuEntity);
                        break;
                    case PAY_SHEET:
                        //付款单：type需根据原系统内回、付款管理是否开启流程确定
                        String planKey = corpid + "_" + FundManagementMenuEnum.PAY_PLAN.getAlias();
                        PaasMenuEntity paymentMenu = corpMenuMap.get(planKey);
                        if (paymentMenu != null) {
                            //type类型置为原回、付款管理的type类型（原回款、付计划和回、付款单共用一个菜单，而回、付款单是否开启流程也是基于原回、付款管理菜单）
                            paasMenuEntity.setType(paymentMenu.getType());
                        }
                        setParentId(corpid, cache, corpMenuMap, paasMenuEntity);
                        break;
                    case PREPAY_BLANCE:
                    case PURCHASE_INVOICE:
                        //预收/付款、进项发票：直接插入（如果重复执行则更新），type类型固定初始化为非流程表单
                        setParentId(corpid, cache, corpMenuMap, paasMenuEntity);
                        break;
                    default:
                        //其他类型跳过不处理
                        continue;
                }
                if (flag) {
                    insertList.add(paasMenuEntity);
                } else {
                    updateList.add(paasMenuEntity);
                }
            }
        }
        try {
            if (insertList.size() > 0) {
                paasMenuModel.insertBatch(insertList);
                LOG.warn(insertList.size() + "条子级菜单（付款单、预付款、进项发票等）插入成功");
            }
            if (updateList.size() > 0) {
                paasMenuModel.updateBatchTemp(updateList);
                LOG.warn(updateList.size() + "条子级菜单（付款管理等）更新成功");
            }
        } catch (Exception e) {
            LOG.error("FundMenuScriptController.handleChildMenu menu数据库批量设置子菜单出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return insertList;
    }

    /**
     * 处理回款单form：把其menuId置为菜单表新插入的【回款单】菜单id
     * 处理menuId、summary、customTitle等
     * @param sheetFormList 回款单formList
     * @param keyPart 此处固定为："_" + FundManagementMenuEnum.PAYMENT_SHEET.getAlias()，需要拼上corpid
     * @param corpMenuMap corpid_alias-菜单
     * @throws XbbException
     * @author zcp
     * @date 19/11/4 004 22:04
     * @update 19/11/4 004 22:04
     * @since v1.0
     * @version v1.0
     */
    private void handleForm4Sheet(List<PaasFormEntityExt> sheetFormList, String keyPart, Map<String, PaasMenuEntity> corpMenuMap) throws XbbException {
        List<PaasFormEntityExt> updateList = new ArrayList<>();

        //String summary = JSON.toJSONString(initMenuHelp.getAppDefaultSummary(XbbRefTypeEnum.PAY_SHEET.getCode()));
        //String customTitle = JSON.toJSONString(initMenuHelp.getAppDefaultTitle(XbbRefTypeEnum.PAY_SHEET.getCode()));
        for (PaasFormEntityExt entityExt : sheetFormList) {
            PaasMenuEntity paasMenuEntity = corpMenuMap.get(entityExt.getCorpid() + keyPart);
            if (paasMenuEntity == null) {
                continue;
            }
            //把回款单form的menuId置为菜单表新插入的【回款单】菜单id
            entityExt.setMenuId(paasMenuEntity.getId());
            //entityExt.setSummary(summary);
            //entityExt.setCustomTitle(customTitle);
            updateList.add(entityExt);
        }
        try {
            if (updateList.size() > 0) {
                paasFormModel.updateBatchTemp(updateList);
                LOG.warn("tb_paas_form：" + updateList.size() + "条付款单menuId更新成功");
            }
        } catch (Exception e) {
            LOG.error("FundMenuScriptController.handleForm4Sheet form数据库批量设置出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    /**
     * 设置子菜单的parentId
     * @param corpid 公司类型
     * @param cache 资金管理菜单枚举
     * @param corpMenuMap corpid_alias-菜单
     * @param paasMenuEntity 菜单实体
     * @author zcp
     * @date 19/11/4 004 19:18
     * @update 19/11/4 004 19:18
     * @since v1.0
     * @version v1.0
     */
    private void setParentId(String corpid, FundManagementMenuEnum cache, Map<String, PaasMenuEntity> corpMenuMap, PaasMenuEntity paasMenuEntity) {
        String parentKey = corpid + "_" + cache.getParent();
        PaasMenuEntity parentMenu = corpMenuMap.get(parentKey);
        if (parentMenu != null) {
            paasMenuEntity.setParentId(parentMenu.getId());
        }
    }

    /**
     * 根据回款单刷预收款余额
     * @param initFundMenuDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/initPaymentBalance", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String initPaymentBalance(@RequestBody @Valid InitFundMenuDTO initFundMenuDTO, BindingResult br) throws Exception {
        XbbResponse<ScriptVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
            return JSON.toJSONString(response);
        } else {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("orderByStr", "id");
            params.put("del", 0);
            params.put("pageSize", 10000);
            //按公司刷，不传则是全部公司的数据
            List<String> corpidList = initFundMenuDTO.getCorpidList();
            if(CollectionsUtil.isNotEmpty(corpidList)){
                params.put("corpidIn", corpidList);
            }
            boolean flag = true;
            Integer a= 0;
            while (flag) {
                List<PaymentSheetEntityExt> list = paymentSheetModel.findAffectBalanceEntitys(params);
                if (list == null || list.isEmpty()) {
                    flag = false;
                } else {
                    PaymentSheetEntityExt paymentSheetEntityExt = list.get(list.size() - 1);
                    params.put("idGte", paymentSheetEntityExt.getId());
                    for (PaymentSheetEntityExt sheetEntityExt : list) {
                        try {
                            saasPaymentSheetHelper.saveByPaymentSheet(sheetEntityExt, DistributorMarkEnum.DISTRIBUTOR.getCode());
                            a++;
                            LOG.info("======"+a);
                        } catch (Exception e) {
                            LOG.error("",e);
                        }
                    }
                }
            }
        }
        return JSON.toJSONString("{\"msg\":\"success\"}");
    }


    /**
     * 删除未开通进销存却有付款管理的菜单
     * @param initFundMenuDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/deletePayPlan", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String deletePayPlan(@RequestBody @Valid InitFundMenuDTO initFundMenuDTO, BindingResult br) throws Exception {
        XbbResponse<ScriptVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
            return JSON.toJSONString(response);
        } else {
            if (!proBaseConfig.getXbbCode().equals(initFundMenuDTO.getXbbCode())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
            }
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.DEL, 0);
            param.put("alias", XbbRefTypeEnum.JXC.getAlias());
            List<PaasAppEntity> jxcAppList = paasAppModel.findEntitys(param);
            Map<String, PaasAppEntity> jxcAppMap = new HashMap<>(jxcAppList.size());
            jxcAppList.forEach(item->{
                jxcAppMap.put(item.getCorpid(), item);
            });
            int pageSize = 1000;
            Map<String, Object> menuParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            menuParam.put("del", 0);
            menuParam.put("creatorId", "1");
            menuParam.put("alias", XbbRefTypeEnum.PAY_PLAN.getAlias());
            Long startTime = DateTimeUtil.getInt("2020-01-14 00:00:00");
            menuParam.put("startAddTime", startTime);
            Long endTime = DateTimeUtil.getInt("2020-01-14 23:59:59");
            menuParam.put("endAddTime", endTime);
            List<PaasMenuEntity> menuList = paasMenuModel.findEntitys(menuParam);
            int total = menuList.size();
            List<Long> deleteMenuList = new ArrayList<>();
            for (int i = 0; i < total; i++) {
                PaasMenuEntity paasMenuEntity = menuList.get(i);
                if (!jxcAppMap.containsKey(paasMenuEntity.getCorpid())) {
                    deleteMenuList.add(paasMenuEntity.getId());
                    LOG.warn("查询未开通进销存却有付款管理的菜单，第" + i + "个1000/" + total);
                }
            }
            int deleteTotal = deleteMenuList.size();
            LOG.warn("查询未开通进销存却有付款管理的菜单，共有：" + deleteTotal + "条");
            for (int i = 0; i < deleteTotal; i += pageSize) {
                int toIndex = i + pageSize;
                if (toIndex>deleteTotal) {
                    toIndex = deleteTotal;
                }
                List<Long> idIn = deleteMenuList.subList(i, toIndex);
                if (CollectionsUtil.isNotEmpty(idIn)) {
                    paasMenuModel.deleteBatch(idIn, null);
                    LOG.warn("删除未开通进销存却有付款管理的菜单，第" + i + "个1000/" + deleteTotal);
                }
            }
            LOG.warn("-----------处理完毕-----------");
        }
        return JSON.toJSONString("{\"msg\":\"success\"}");
    }

    /**
     * 删除未开通进销存却有付款管理的菜单
     * @param initFundMenuDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/deletePayPlanRelated", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String deletePayPlanRelated(@RequestBody @Valid InitFundMenuDTO initFundMenuDTO, BindingResult br) throws Exception {
        XbbResponse<ScriptVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
            return JSON.toJSONString(response);
        } else {
            if (!proBaseConfig.getXbbCode().equals(initFundMenuDTO.getXbbCode())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
            }
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.DEL, 0);
            param.put("alias", XbbRefTypeEnum.JXC.getAlias());
            param.put("columns", "corpid");
            List<PaasAppEntity> jxcAppList = paasAppModel.findEntitys(param);
            Map<String, PaasAppEntity> jxcAppMap = new HashMap<>(jxcAppList.size());
            jxcAppList.forEach(item->{
                jxcAppMap.put(item.getCorpid(), item);
            });
            List<String> aliasIn = new ArrayList<>();
            List<FundManagementMenuEnum> fundList = FundManagementMenuEnum.getJxcFund();
            fundList.forEach(item->{
                aliasIn.add(item.getAlias());
            });
            int pageSize = 1000;
            Map<String, Object> menuParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            menuParam.put("del", 0);
            menuParam.put("creatorId", "1");
            menuParam.put("aliasIn", aliasIn);
            Long startTime = DateTimeUtil.getInt("2020-05-30 00:00:00");
            menuParam.put("startAddTime", startTime);
            Long endTime = DateTimeUtil.getInt("2020-05-30 08:00:00");
            menuParam.put("endAddTime", endTime);
            List<PaasMenuEntity> menuList = paasMenuModel.findEntitys(menuParam);
            int total = menuList.size();
            List<Long> deleteMenuList = new ArrayList<>();
            for (int i = 0; i < total; i++) {
                PaasMenuEntity paasMenuEntity = menuList.get(i);
                if (!jxcAppMap.containsKey(paasMenuEntity.getCorpid())) {
                    deleteMenuList.add(paasMenuEntity.getId());
                    LOG.warn("查询未开通进销存却有付款管理的菜单，第" + i + "个1000/" + total);
                }
            }
            int deleteTotal = deleteMenuList.size();
            LOG.warn("查询未开通进销存却有付款管理的菜单，共有：" + deleteTotal + "条");
            for (int i = 0; i < deleteTotal; i += pageSize) {
                int toIndex = i + pageSize;
                if (toIndex>deleteTotal) {
                    toIndex = deleteTotal;
                }
                List<Long> idIn = deleteMenuList.subList(i, toIndex);
                if (CollectionsUtil.isNotEmpty(idIn)) {
                    paasMenuModel.deleteBatch(idIn, null);
                    paasFormModel.deleteBatchByMenuId(idIn, null);
                    paasFormExplainModel.deleteBatchByMenuId(idIn, null);
                    LOG.warn("删除未开通进销存却有付款管理的菜单，第" + i + "个1000/" + deleteTotal);
                }
            }
            LOG.warn("-----------处理完毕-----------");
        }
        return JSON.toJSONString("{\"msg\":\"success\"}");
    }


}
